import { t } from 'i18next';
import { useFormContext, UseFormReturn } from 'react-hook-form';

import { Button } from '@/components/ui/button';
import {
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { flagsHooks } from '@/hooks/flags-hooks';
import { OAuth2App, oauth2Utils } from '@/lib/oauth2-utils';
import {
  OAuth2Property,
  OAuth2Props,
  PieceMetadataModel,
  PieceMetadataModelSummary,
} from '@activepieces/pieces-framework';
import {
  resolveValueFromProps,
  ApFlagId,
  AppConnectionType,
  OAuth2GrantType,
  UpsertCloudOAuth2Request,
  UpsertOAuth2Request,
  UpsertPlatformOAuth2Request,
  isNil,
} from '@activepieces/shared';

import { AutoPropertiesFormComponent } from '../builder/piece-properties/auto-properties-form';

function OAuth2ConnectionSettings({
  authProperty,
  oauth2App,
  piece,
  grantType,
}: OAuth2ConnectionSettingsProps) {
  const form = useFormContext<{
    request:
      | UpsertCloudOAuth2Request
      | UpsertOAuth2Request
      | UpsertPlatformOAuth2Request;
  }>();
  const isClientIdValid = isNil(
    form.formState.errors.request?.value?.client_id,
  );
  const isClientSecretValid =
    oauth2App.oauth2Type !== AppConnectionType.OAUTH2 ||
    form.getValues('request.value.client_secret');
  const isPropsValid = isNil(form.formState.errors.request?.value?.props);
  const isConnectButtonEnabled =
    isClientIdValid && isClientSecretValid && isPropsValid;
  const { data: thirdPartyUrl } = flagsHooks.useFlag<string>(
    ApFlagId.THIRD_PARTY_AUTH_PROVIDER_REDIRECT_URL,
  );
  const redirectUrl =
    oauth2App.oauth2Type === AppConnectionType.CLOUD_OAUTH2
      ? 'https://secrets.activepieces.com/redirect'
      : thirdPartyUrl ?? 'no_redirect_url_found';

  const hasCode = form.getValues().request.value.code;
  const showRedirectUrlInput =
    oauth2App.oauth2Type === AppConnectionType.OAUTH2 &&
    grantType === OAuth2GrantType.AUTHORIZATION_CODE;
  return (
    <div className="flex flex-col gap-4">
      {showRedirectUrlInput && (
        <div className="flex flex-col gap-2">
          <FormLabel>{t('Redirect URL')}</FormLabel>
          <FormControl>
            <Input disabled type="text" value={redirectUrl} />
          </FormControl>
          <FormMessage />
        </div>
      )}

      {oauth2App.oauth2Type === AppConnectionType.OAUTH2 && (
        <>
          <FormField
            name="request.value.client_id"
            control={form.control}
            render={({ field }) => (
              <FormItem className="flex flex-col">
                <FormLabel>{t('Client ID')}</FormLabel>
                <FormControl>
                  <Input {...field} type="text" placeholder={t('Client ID')} />
                </FormControl>
              </FormItem>
            )}
          ></FormField>
          <FormField
            name="request.value.client_secret"
            control={form.control}
            render={({ field }) => (
              <FormItem className="flex flex-col">
                <FormLabel>{t('Client Secret')}</FormLabel>
                <FormControl>
                  <Input
                    {...field}
                    type="password"
                    placeholder={t('Client Secret')}
                  />
                </FormControl>
              </FormItem>
            )}
          ></FormField>
        </>
      )}
      {authProperty.props && (
        <AutoPropertiesFormComponent
          prefixValue="request.value.props"
          props={authProperty.props}
          useMentionTextInput={false}
          allowDynamicValues={false}
        />
      )}

      {grantType !== OAuth2GrantType.CLIENT_CREDENTIALS && (
        <div className="border border-solid p-2 rounded-lg gap-2 flex text-center items-center justify-center h-full">
          <div className="rounded-full border border-solid p-1 flex items-center justify-center">
            <img src={piece.logoUrl} className="w-5 h-5"></img>
          </div>
          <div className="text-sm">{piece.displayName}</div>
          <div className="flex-grow"></div>
          <Button
            size={'sm'}
            variant={'basic'}
            className={hasCode ? 'text-destructive' : ''}
            disabled={!isConnectButtonEnabled}
            type="button"
            onClick={async () => {
              if (!hasCode) {
                openPopup(
                  redirectUrl,
                  form.getValues().request.value.client_id,
                  form.getValues().request.value.props,
                  authProperty,
                  form,
                );
              } else {
                form.setValue('request.value.code', '', {
                  shouldValidate: true,
                });
                form.setValue('request.value.code_challenge', '', {
                  shouldValidate: true,
                });
              }
            }}
          >
            {hasCode ? t('Disconnect') : t('Connect')}
          </Button>
        </div>
      )}
    </div>
  );
}

OAuth2ConnectionSettings.displayName = 'OAuth2ConnectionSettings';
export { OAuth2ConnectionSettings };

async function openPopup(
  redirectUrl: string,
  clientId: string,
  props: Record<string, unknown> | undefined,
  authProperty: OAuth2Property<OAuth2Props>,
  form: UseFormReturn<{
    request:
      | UpsertCloudOAuth2Request
      | UpsertOAuth2Request
      | UpsertPlatformOAuth2Request;
  }>,
) {
  const scope = resolveValueFromProps(props, authProperty.scope.join(' '));
  const authUrl = resolveValueFromProps(props, authProperty.authUrl);
  const { code, codeChallenge } = await oauth2Utils.openOAuth2Popup({
    authUrl,
    clientId,
    redirectUrl,
    scope,
    prompt: authProperty.prompt,
    pkce: authProperty.pkce ?? false,
    pkceMethod: authProperty.pkceMethod ?? 'plain',
    extraParams: authProperty.extra ?? {},
  });
  form.setValue('request.value.code', code, { shouldValidate: true });
  form.setValue('request.value.code_challenge', codeChallenge, {
    shouldValidate: true,
  });
}

type OAuth2ConnectionSettingsProps = {
  piece: PieceMetadataModelSummary | PieceMetadataModel;
  authProperty: OAuth2Property<OAuth2Props>;
  oauth2App: OAuth2App;
  grantType: OAuth2GrantType;
};
